﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Collections;
using System.Runtime.InteropServices;

using SuperMapLib;

namespace JR_RouteAlarm
{
    public class RouteDivision
    {
        private const string DIVISION_ROUTE = "路線分け";
        private const string DIVISION_LABEL = "ラベル分け";
        private const string AREA_CD = "area_cd";
        private soDataSources objSources = null;

        /// <summary>
        /// データソース集合と新たなデータソースの初期化
        /// </summary>
        /// <param name="superWksp">ワークスペース</param>
        public RouteDivision(AxSuperMapLib.AxSuperWorkspace superWksp)
        {
            soDataSource objSource = null;

            objSources = superWksp.Datasources;
            Console.WriteLine("datasource count:\t" + objSources.Count.ToString());
            if (objSources[DIVISION_ROUTE] != null)
            {
                objSources.Remove(DIVISION_ROUTE);
            }
            objSource = superWksp.CreateDataSource(
                DIVISION_ROUTE + ".sdb", DIVISION_ROUTE, seEngineType.sceSDBPlus,
                false, false, false, "");

            if (objSources[DIVISION_LABEL] != null)
            {
                objSources.Remove(DIVISION_LABEL);
            }
            objSource = superWksp.CreateDataSource(
                DIVISION_LABEL + ".sdb", DIVISION_LABEL, seEngineType.sceSDBPlus, 
                false, false, false, "");
        }

        /// <summary>
        /// 線路とラベルを分ける
        /// </summary>
        public void MakeDivision()
        {
            soDataSource objSource = null;
            soDataset objDSALLRoute = null;
            soDataset objDSText = null;
            soRecordset objRSTextALL = null;

            objSource = objSources["CHECK"];
            objDSALLRoute = objSource.Datasets["全線路"];
            objSource = objSources["areamap"];
            objDSText = objSource.Datasets["ラベルテキスト"];

            soDatasetVector objVectorText = objDSText as soDatasetVector;
            objRSTextALL = objVectorText.Query("", true, null, "");

            BuildRoutes(objDSALLRoute, objRSTextALL, objSources[DIVISION_LABEL]);

            Marshal.ReleaseComObject(objDSALLRoute);
            objDSALLRoute = null;
            Marshal.ReleaseComObject(objSource);
            objSource = null;
            Marshal.ReleaseComObject(objSources);
            objSources = null;
        }

        /// <summary>
        /// 分ける線路を作成
        /// </summary>
        /// <param name="objDSALLRoute">対象線路データセット</param>
        /// <param name="objRSTextALL">対象ラベルテキストデータセット</param>
        /// <param name="objSource">保存するラベルデータソース</param>
        private void BuildRoutes(soDataset objDSALLRoute, soRecordset objRSTextALL, soDataSource objSource)
        {
            soDatasetVector objVector = null;
            soRecordset objRS = null;
            soStrings objStrings = null;

            objStrings = new soStrings();
            objStrings.Add(String.Format("distinct(left(ltrim({0}), 2))", AREA_CD));

            objVector = objDSALLRoute as soDatasetVector;
            Console.WriteLine("datasource count:\t" + objSources.Count.ToString());
            Console.WriteLine(objVector.TableName + "\t---" + objStrings[1].ToString());
            objRS = objVector.Query("", 
                false, objStrings, "");

            Marshal.ReleaseComObject(objStrings);
            objStrings = null;

            if (objRS != null && objRS.RecordCount > 0)
            {
                if (!objRS.IsBOF())
                {
                    objRS.MoveFirst();
                }
                //string strTarget = "TO,CL,YK,YH,TU,MS";
                //string strTarget = "CL";
                //string strTarget = "TH,TK";
                string strTarget = "AG";
                //string strTarget = "YD";
                for (int i = 0; !objRS.IsEOF(); objRS.MoveNext(), i++)
                {
                    soRecordset objRSRoute = null;
                    string strAreaName = objRS.GetFieldValueText(1);
                    if (strTarget.Contains(strAreaName.Substring(0, 2)))
                    {
                        objRSRoute = objVector.Query(
                            String.Format("left(ltrim({0}), 2) = '{1}'", AREA_CD, strAreaName),
                            true, null, "");
                        //String.Format("order by {0}", AREA_CD));
                        if (objSources[DIVISION_ROUTE].RecordsetToDataset(objRSRoute, strAreaName == "TO" ? "TO_bak" : strAreaName, false) != null)
                        {
                            Console.WriteLine("dataset「" + strAreaName + "」を作成しました！\t---" + (i + 1).ToString());

                            if (!objRSRoute.IsBOF())
                            {
                                objRSRoute.MoveFirst();
                            }
                            string strDSName = "Label_" + strAreaName;
                            soDataset objDSTextNew = null;
                            soRecordset objRSTextNew = null;
                            //soDatasetVector objVectorText = objDSText as soDatasetVector;
                            //soRecordset objRSTextALL = objVectorText.Query("", true, null, "");
                            if (objSource.IsAvailableDatasetName(strDSName))
                            {
                                objDSTextNew = objSources[DIVISION_LABEL].CreateDataset(
                                    strDSName, seDatasetType.scdText, seDatasetOption.scoDefault, null);
                                objRSTextNew = (objDSTextNew as soDatasetVector).Query("1 < 0", true, null, "");
                            }
                            for (; !objRSRoute.IsEOF(); objRSRoute.MoveNext())
                            {
                                Console.WriteLine(objRSRoute.GetFieldValueText(AREA_CD).Trim());
                                BuildTexts(objRSTextNew, objRSTextALL, objRSRoute.GetFieldValueText(AREA_CD).Trim());
                            }

                            //objVectorText.Close();
                            //Marshal.ReleaseComObject(objVectorText);
                            //objVectorText = null;
                            ////Marshal.ReleaseComObject(objDSTextNew);
                            ////objDSTextNew = null;
                            //objRSTextNew.Close();
                            //Marshal.ReleaseComObject(objRSTextNew);
                            //objRSTextNew = null;
                            //objRSTextALL.Close();
                            //Marshal.ReleaseComObject(objRSTextALL);
                            //objRSTextALL = null;
                        }
                        else
                        {
                            Console.WriteLine("「" + strAreaName + "」" + "が失敗！@\t---" + (i + 1).ToString());
                        }

                        objRSRoute.Close();
                        Marshal.ReleaseComObject(objRSRoute);
                        objRSRoute = null;
                    }
                }
            }

            objRS.Close();
            Marshal.ReleaseComObject(objRS);
            objRS = null;
            objVector.Close();
            Marshal.ReleaseComObject(objVector);
            objVector = null;
        }

        /// <summary>
        /// 分けるラベルを作成
        /// </summary>
        /// <param name="objRSTextNew">対象ラベルレコードセット</param>
        /// <param name="objRSTextALL">全部ラベルレコードセット</param>
        /// <param name="strAreaCD">対象線路エリアコード</param>
        private void BuildTexts(soRecordset objRSTextNew, soRecordset objRSTextALL, string strAreaCD)
        {
            if (objRSTextALL != null && objRSTextALL.RecordCount > 0)
            {
                if (!objRSTextALL.IsBOF())
                {
                    objRSTextALL.MoveFirst();
                }

                for (int i = 0; !objRSTextALL.IsEOF(); objRSTextALL.MoveNext(), i++)
                {
                    soGeoText objText = objRSTextALL.GetGeometry() as soGeoText;

                    soGeoText objTextTmp = null;
                    soTextPart objTextPart = objText.GetPartAt(1);
                    string strText = objTextPart.Text;
                    //Console.WriteLine(strText + "\t---" + objText.PartCount.ToString());
                    if (!strText.StartsWith(strAreaCD) || strText.Contains("他線区") || strAreaCD.Contains("KW") || strAreaCD.Contains("TF"))
                    {
                        continue;
                    }
                    strText = string.Empty;
                    FormatAreaSubList(objText, ref strText);
                    objTextPart.Text = strText;

                    objTextTmp = new soGeoText();
                    objTextTmp.TextStyle.FixedSize = true;
                    objTextTmp.TextStyle.FixedTextSize = 50;
                    objTextTmp.TextStyle.FontHeight = 177;
                    objTextTmp.TextStyle.Align = seTextAlign.sctTopLeft;
                    //objTextTmp.TextStyle.FontWidth = 0;
                    objTextTmp.AddPart(objTextPart);
                    if (objRSTextNew.AddNew(objTextTmp as soGeometry, null) > 0)
                    {
                        if (objRSTextNew.Update() > 0)
                        {
                            Console.WriteLine(strText + "\n追加しました！\t---" + (i + 1).ToString());
                        }
                        else
                        {
                            Console.WriteLine(strText + "\n更新失敗しました！\t---" + (i + 1).ToString());
                        }
                    }
                    else
                    {
                        Console.WriteLine("Add new 失敗！\n" + strText + "\t---" + (i + 1).ToString());
                    }

                    //Marshal.ReleaseComObject(objTextTmp);
                    //objTextTmp = null;
                    //Marshal.ReleaseComObject(objTextPart);
                    //objTextPart = null;
                    //Marshal.ReleaseComObject(objText);
                    //objText = null;

                    break;
                }
            }
        }

        /// <summary>
        /// エリア毎に、ラベル内容をフォーマット
        /// </summary>
        /// <param name="objText">対象ラベルのテキストオブジェクト</param>
        /// <param name="strText">フォーマットするテキスト</param>
        private void FormatAreaSubList(soGeoText objText, ref string strText)
        {
            ArrayList arrAlarmRoute = new ArrayList();
            ArrayList arrAlarmArea = new ArrayList();
            ArrayList arrLength = new ArrayList();
            string strTextIdxStr = objText.IndexString;

            string[] strAlarmRoute = strTextIdxStr.Substring(
                strTextIdxStr.IndexOf(')') + 2).Split(
                    new Char[] { '線', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < strAlarmRoute.Length; i++)
            {
                if (strAlarmRoute[i].Trim() == "" || strAlarmRoute[i] == "ALL")
                {
                    continue;
                }
                else if (strAlarmRoute[i].IndexOf('-') > 0)
                {
                    arrAlarmArea.Add(strAlarmRoute[i]);
                    continue;
                }
                arrAlarmRoute.Add("　" + strAlarmRoute[i] + "線");
                arrLength.Add(strAlarmRoute[i].Length);
            }
            arrLength.Sort();
            int maxLength = Convert.ToInt32(arrLength[arrLength.Count - 1]) + 2;
            strText = strTextIdxStr.Insert(strTextIdxStr.IndexOf('('), " ");
            strText = strText.Substring(0, strText.IndexOf(')') + 1) + "\n";
            for (int i = 0; i < arrAlarmRoute.Count; i++)
            {
                strText += arrAlarmRoute[i].ToString().PadRight(maxLength, '　')
                    + " (" + arrAlarmArea[i].ToString() + ")" + "\n";
            }
        }
    }
}
